package com.central;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
//import java.util.Date;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;


import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class Central implements ICentral
{
	/*
	 * Le but de cette classe est :
	 * - de pouvoir renvoyer la liste de produits commandés pour la réservation (méthode 'trans_listCommand')
	 * - de pouvoir renvoyer la date de livraison et le coût après chaque insertion d'un nouveau produit (méthode 'calculDelai_Cout')
	 * (cela émet une réservation d'office)
	 * - de pouvoir valider une réservation
	 */
	
	private Socket skt;
	private BufferedReader in;
	private PrintWriter out;
	
	private String ipAtt0;
	private Integer portAtt0;
	private String ipAtt1;
	private Integer portAtt1;
	private String ipAtt2;
	private Integer portAtt2;
	private String ipAtt3;
	private Integer portAtt3;
	private String ipAtt4;
	private Integer portAtt4;
	private  Hashtable<Integer, Integer[]> prdts = new Hashtable<Integer, Integer[]>();

	public static void main(String args[]) 
	{
		new Central();
	}
	
	
	public Central() 
	{
		try {
			configConnexion();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
	}

	private void configConnexion() throws UnknownHostException 
	{
		//Setting des adresses IP et des ports
		ipAtt0 = "127.0.0.1";
		ipAtt1 = "127.0.0.1";
		ipAtt2 = "127.0.0.1";
		ipAtt3 = "127.0.0.1";
		ipAtt4 = "127.0.0.1";
		
		portAtt0 = 10001;
		portAtt1 = 10002;
		portAtt2 = 10003;
		portAtt3 = 10004;
		portAtt4 = 10005;
	}

	/**
	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% new implementation %%%%%%%%%%%%
	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	 * Fonction de calcul du délai et du coût
	 * Résultat attendu :
	 * JSONObject [] composé de la date de livraison et du coût
	 * @param codeLivraison
	 * @param Id
	 * @param qte
	 * @param prixUnit
	 * @return
	 * @throws UnknownHostException
	 * @throws IOException
	 * @throws JSONException
	 */
	int delai = 1;// global variable for process
	int cout = 0;
	String note = "";
	//JSONArray bookJsonA = new JSONArray();
	public JSONObject delay(Integer codeLivraison, Integer Id, Integer qte, Integer prixUnit) throws UnknownHostException, IOException, JSONException
	{
		String inetAddresses = "127.0.0.1";
		JSONObject jsonOut = new JSONObject();
		int cp = codeLivraison;

		try{//tests if the server responds
			skt = new Socket(inetAddresses,codeLivraison);
		}catch(ConnectException e){
			codeLivraison++;//else try next server
			e.printStackTrace();
		}
		// reader and writer
		in = new BufferedReader(new InputStreamReader(skt.getInputStream()));
		out = new PrintWriter(skt.getOutputStream(), true);
		// set the json with starts values
		jsonOut.put("message", "book");
		jsonOut.put("productId", Id);
		jsonOut.put("wantedQty", qte);
		out.println(jsonOut);// send request to threadSite
		//JSONObject bookJ = new JSONObject();//the json for record bookedQty and in which server
		while(!in.ready());
		String line = in.readLine();// get response from server
		//System.out.println("########### ( 128 ) line "+line);
		JSONObject jsonIn = new JSONObject(line);
		//System.out.println("########### ( 130 C ) jsonIn "+jsonIn);
		int availableQty = jsonIn.getInt("availableQty");
		int wantedQty = jsonIn.getInt("wantedQty");
		int booked = jsonIn.getInt("booked");
		//System.out.println("########### ( 132 )booked "+booked);
		
		//bookJ.put("server", codeLivraison);
		//bookJ.put("qty", booked);
		//bookJsonA.put(bookJ);
		int newQty = wantedQty - availableQty;// remaining qty to book
		
		if(codeLivraison >= 10005)// if we are in the last server goto first
			codeLivraison = 10000;
		
		// test if we tried all servers 
		// in that case , stop requesting and fix delay to 1000.... should be improved
		if (delai >5){
			note += "rupture de stock";
			cout = 0;
			delai = 1000;
		}
		
		// if more product to be booked, do this function again (recursivity)
		// 'delai < 6' for not loop again and create an  'infinite-loop'
		else if(newQty > 0 && (codeLivraison >= 10000 && codeLivraison < 10005) && delai < 6){ 
			codeLivraison++;
			delai++;
			this.delay(codeLivraison, Id, newQty, prixUnit);
		}
		// add max delay to current date
		String dateLivraison="";
		if(delai == 1000)
			dateLivraison = "livraison impossible";
		else{
			Date date = new Date();
			Calendar deliveryDate = Calendar.getInstance();
			deliveryDate.add(Calendar.DATE, delai);
			date = deliveryDate.getTime();
			SimpleDateFormat format = new SimpleDateFormat("dd/MM/yy");
			dateLivraison = format.format(date);
		}
		cout = wantedQty*prixUnit;
		jsonIn.put("dateLivraison", dateLivraison);
		jsonIn.put("cout", cout);
		jsonIn.put("note", note);
		//jsonIn.put("bookJsonA", bookJsonA.toString());
		
		return jsonIn;//send to server ajax
	}
	
	/**
	 * Le but de cette fonction est de renvoyer un JSONObject ayant pour structure :
	 * Id : numServerLoc
	 * Value : JSONArray de JSONObject
	 * 			 {Id : idProduit, Value : qte}
	 */
	/*public JSONObject trans_listCommand (Hashtable<Integer, Integer[]> listCommande)
	{
		
		JSONObject jsoListCommand = new JSONObject();
		try 
		{
			//Construction des JSONObject pour chaque site
			JSONObject jsoPrdt1 = new JSONObject();
			JSONObject jsoPrdt2 = new JSONObject();
			JSONObject jsoPrdt3 = new JSONObject();
			JSONObject jsoPrdt4 = new JSONObject();
			JSONObject jsoPrdt5 = new JSONObject();
			
			JSONArray jsaServ1 = new JSONArray();
			JSONArray jsaServ2 = new JSONArray();
			JSONArray jsaServ3 = new JSONArray();
			JSONArray jsaServ4 = new JSONArray();
			JSONArray jsaServ5 = new JSONArray();
			
			Object i;
			if(listCommande.size()!=0)
			{
				@SuppressWarnings("rawtypes")
				Enumeration enu=listCommande.keys();
				Integer[] n = new Integer[7];

				while(enu.hasMoreElements())
				{
					i = enu.nextElement();
					n = listCommande.get(i);
					if(!n[0].equals(null)&&!n[0].equals(0))
					{
						jsoPrdt1.put( i.toString() , n[0]);
						System.out.println(jsoPrdt1.toString());
						jsaServ1.put(jsoPrdt1);
						System.out.println(jsaServ1);
					}

					if(!n[1].equals(null)&&!n[1].equals(0))
					{
						jsoPrdt2.put(i.toString(), n[1]);
						jsaServ2.put(jsoPrdt2);
					}

					if(!n[2].equals(null)&&!n[2].equals(0))
					{
						jsoPrdt3.put(i.toString(), n[2]);
						jsaServ3.put(jsoPrdt3);
					}

					if(!n[3].equals(null)&&!n[3].equals(0))
					{
						jsoPrdt4.put(i.toString(), n[3]);
						jsaServ4.put(jsoPrdt4);
					}

					if(!n[4].equals(null)&&!n[4].equals(0))
					{
						jsoPrdt5.put(i.toString(), n[4]);
						jsaServ5.put(jsoPrdt5);
					}
				}
				
				jsoListCommand.put("1",jsaServ1);
				jsoListCommand.put("2",jsaServ2);
				jsoListCommand.put("3",jsaServ3);
				jsoListCommand.put("4",jsaServ4);
				jsoListCommand.put("5",jsaServ5);
				System.out.println(jsaServ1.toString());
			}
		} 
		catch (JSONException e) 
		{
			e.printStackTrace();
		} System.out.println("########### ( jsoListCommand ) "+jsoListCommand);
		return jsoListCommand;
	}*/
	
	public void connexion (String inetAddresses, int port) throws UnknownHostException, IOException
	{
		//Chargement des variables en vu d'une communication
		//Ouverture du socket
		skt = new Socket(inetAddresses, port);
		//Mise en buffer du stream émis par le socket
		in = new BufferedReader(new InputStreamReader(skt.getInputStream()));
		//Préparation de l'émetteur vers le socket client
		out = new PrintWriter(skt.getOutputStream(), true);
	}

	public void quit ()
	{
		try 
		{
			in.close();
			skt.close();
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
		}
	}
	
	public boolean identification (String login, String password)
	{
		return false;		
	}

	@Override
	public JSONObject calculDelai_Cout(Integer codeLivraison, Integer Id,
			Integer qte, Integer prixUnit) throws UnknownHostException,
			IOException, JSONException {
		// TODO Auto-generated method stub
		return null;
	}
}